const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
const BASE58_MAP = new Map(Array.from(BASE58_ALPHABET, (char, index) => [char, index]))

// 统一输入类型处理
function toBytes(input: string | Uint8Array): Uint8Array {
    return typeof input === 'string'
        ? new TextEncoder().encode(input)
        : input
}

export function base58Encode(input: string | Uint8Array): string {
    const bytes = toBytes(input)
    let result = ''

    // 处理前导零
    let leadingZeros = 0
    while (bytes[leadingZeros] === 0 && leadingZeros < bytes.length) {
        leadingZeros++
    }

    // 转换为BigInt
    let num = BigInt(0)
    for (const byte of bytes) {
        num = num * BigInt(256) + BigInt(byte)
    }

    // Base58编码
    while (num > 0) {
        const remainder = Number(num % BigInt(58))
        num = num / BigInt(58)
        result = BASE58_ALPHABET[remainder] + result
    }

    // 添加前导'1'
    return '1'.repeat(leadingZeros) + result || '1'
}

export function base58Decode(input: string): Uint8Array {
    let num = BigInt(0)
    let leadingOnes = 0

    // 验证输入合法性
    if (!/^[1-9A-HJ-NP-Za-km-z]+$/.test(input)) {
        throw new Error('Invalid Base58 string')
    }

    // 处理前导'1'
    while (input[leadingOnes] === '1' && leadingOnes < input.length) {
        leadingOnes++
    }

    // 转换为BigInt
    for (const char of input.slice(leadingOnes)) {
        const value = BASE58_MAP.get(char)
        if (value === undefined) throw new Error('Invalid character')
        num = num * BigInt(58) + BigInt(value)
    }

    // 转换为字节数组
    const bytes: number[] = []
    while (num > 0) {
        bytes.unshift(Number(num % BigInt(256)))
        num = num / BigInt(256)
    }

    return new Uint8Array([
        ...new Array(leadingOnes).fill(0),
        ...bytes
    ])
}

export const unit8ArrayToString = (ua: Uint8Array): string => {
    // 处理空数据边界情况
    if (ua.length === 0) return ''

    // 显式指定UTF-8解码（兼容中文）
    try {
        return new TextDecoder('utf-8', { fatal: true }).decode(ua)
    } catch (e) {
        throw new Error(`解码失败: ${e instanceof Error ? e.message : String(e)}`)
    }
}